home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / asmutil / 68kdis.zip / ALLOC.C next >
C/C++ Source or Header  |  1988-12-03  |  6KB  |  337 lines

  1. /*
  2.  *    SCCS:    @(#)alloc.c    1.2    11/2/84    14:17:20
  3.  *    Allocate space etc.
  4.  *
  5.  ***********************************************************************
  6.  *    This software is copyright of
  7.  *
  8.  *        John M Collins
  9.  *        47 Cedarwood Drive
  10.  *        St Albans
  11.  *        Herts, AL4 0DN
  12.  *        England            +44 727 57267
  13.  *
  14.  *    and is released into the public domain on the following conditions:
  15.  *
  16.  *        1.  No free maintenance will be guaranteed.
  17.  *        2.  Nothing may be based on this software without
  18.  *            acknowledgement, including incorporation of this
  19.  *            notice.
  20.  *
  21.  *    Notwithstanding the above, the author welcomes correspondence and bug
  22.  *    fixes.
  23.  ***********************************************************************
  24.  */
  25.  
  26. #include <stdio.h>
  27. #include <a.out.h>
  28. #include <setjmp.h>
  29. #include <ldfcn.h>
  30. #include "unc.h"
  31.  
  32. #define    STINC    10
  33.  
  34. char    *malloc(), *realloc();
  35. char    *strncpy();
  36. void    gette(), getde(), setde(), putte(), putde();
  37. void    unimpl();
  38. long    gettw();
  39.  
  40. ef_fids    mainfile;
  41.  
  42. /*
  43.  *    Oops! out of memory.....
  44.  */
  45.  
  46. void    nomem()
  47. {
  48.     (void) fprintf(stderr, "Sorry - run out of memory\n");
  49.     exit(255);
  50. }
  51.  
  52. /*
  53.  *    Look up hash value of symbol.
  54.  */
  55.  
  56. unsigned  shash(str)
  57. register  char    *str;
  58. {
  59.     register  unsigned  result = 0;
  60.     register  int    cnt = 0;
  61.     
  62.     while  (*str  &&  cnt < MAXCHARS)  {
  63.         result += *str++;
  64.         cnt++;
  65.     }
  66.     return  result % HASHMOD;
  67. }
  68.  
  69. /*
  70.  *    Look up hash value of symbol, possibly allocating a new symbol.
  71.  */
  72.  
  73. symbol    lookup(str)
  74. char    *str;
  75. {
  76.     register  symbol  res, *pp;
  77.     register  int    len;
  78.     
  79.     pp = &symbhash[shash(str)];
  80.     res = *pp;
  81.     while  (res != NULL)  {
  82.         if  (strncmp(res->s_name, str, MAXCHARS) == 0)
  83.             return    res;
  84.         pp = &res->s_next;
  85.         res = *pp;
  86.     }
  87.     for  (len = 0;  len < MAXCHARS;  len++)
  88.         if  (str[len] == '\0')
  89.             break;
  90.     len++;
  91.     res = (symbol) malloc(sizeof(struct symstr) + len);
  92.     if  (res == NULL)
  93.         nomem();
  94.     *pp = res;
  95.     res->s_next = NULL;
  96.     (void) strncpy(res->s_name, str, len);
  97.     res->s_name[len] = '\0';        /*  Null-terminate  */
  98.     res->s_newsym = 1;
  99.     res->s_glob = 0;
  100.     res->s_invent = 0;
  101.     res->s_link = NULL;
  102.     res->s_used = 0;
  103.     res->s_defs = 0;
  104.     res->s_lsymb = 0;
  105.     return  res;
  106. }
  107.  
  108. /*
  109.  *    Invent a symbol, making sure that we don't know it.
  110.  */
  111.  
  112. symbol    inventsymb(prefix)
  113. char    *prefix;
  114. {
  115.     static    int  nsymb = 0;
  116.     char    schars[10];
  117.     register  symbol  res;
  118.     
  119.     do    (void) sprintf(schars, "%s%d", prefix, ++nsymb);
  120.     while  (!(res = lookup(schars))->s_newsym);
  121.     
  122.     res->s_newsym = 0;
  123.     res->s_invent = 1;
  124.     return    res;
  125. }
  126.      
  127. /*
  128.  *    Reallocate symbol table.
  129.  */
  130.  
  131. void    reallst(outf)
  132. register  ef_fid  outf;
  133. {
  134.     outf->ef_stmax += STINC;
  135.     if  (outf->ef_stvec == NULL)
  136.         outf->ef_stvec = (symbol *) malloc(outf->ef_stmax * sizeof(symbol));
  137.     else
  138.         outf->ef_stvec = (symbol *) realloc(outf->ef_stvec,
  139.                     outf->ef_stmax * sizeof(symbol));
  140.     if  (outf->ef_stvec == NULL)
  141.         nomem();
  142. }
  143.  
  144. /*
  145.  *    Search through existing symbol table for symbol with given
  146.  *    value.  Invent a new one if needed.
  147.  */
  148.  
  149. symbol    getnsymb(fid, seg, pos)
  150. register  ef_fid  fid;
  151. unsigned  seg;
  152. long    pos;
  153. {
  154.     register  int    i;
  155.     register  symbol  res;
  156.     
  157.     /***********  MACHINE DEPENDENT  ******************************
  158.      *    Convert relocation segment type (argument) to symbol type
  159.      *    (as remembered in symbol table).  Don't ask me why they
  160.      *    have to be different.....
  161.      */
  162.     
  163.     /*
  164.      *    See if the reference is to an external symbol.
  165.      *    If so, use that.
  166.      */
  167.     
  168.     for  (i = 0;  i < fid->ef_stcnt;  i++)  {
  169.         res = fid->ef_stvec[i];
  170.         if  (res->s_type == seg  &&  res->s_value == pos)
  171.             return    res;
  172.     }
  173.     
  174.     /*
  175.      *    Invent a symbol and use that.
  176.      */
  177.     
  178.     res = inventsymb("RS");
  179.     if  (fid->ef_stcnt >= fid->ef_stmax)
  180.         reallst(fid);
  181.     fid->ef_stvec[fid->ef_stcnt++] = res;
  182.     res->s_type = seg;
  183.     res->s_value = pos;
  184.     if  (seg == S_TEXT)  {
  185.         t_entry    tent;
  186.         gette(fid, pos, &tent);
  187.         tent.t_bdest = 1;
  188.         tent.t_lab = res;
  189.         putte(fid, pos, &tent);
  190.     }
  191.     else  if  (seg == S_DATA  ||  seg == S_BSS)  {
  192.         d_entry dent;
  193.         getde(fid, pos, &dent);
  194.         dent.d_lab = res;
  195.         putde(fid, pos, &dent);
  196.     }
  197.  
  198.     return    res;
  199. }
  200.  
  201. /*
  202.  *    Assuming address given is in text segment, find its label, or invent
  203.  *    one.  Also set where refered from.
  204.  */
  205.  
  206. symbol    textlab(loc, refpos)
  207. long    loc, refpos;
  208. {
  209.     t_entry    tent;
  210.  
  211.     gette(&mainfile, loc, &tent);
  212.     if  (tent.t_type == T_CONT)
  213.         return    NULL;
  214.     if  (tent.t_lab == NULL)  {
  215.         tent.t_lab = inventsymb("TS");
  216.         tent.t_lab->s_type = S_TEXT;
  217.         tent.t_lab->s_value = loc;
  218.         tent.t_bdest = 1;
  219.         putte(&mainfile, loc, &tent);
  220.     }
  221.     else
  222.         tent.t_lab->s_used++;
  223.     if  (tent.t_refhi < refpos)  {
  224.         tent.t_refhi = refpos;
  225.         putte(&mainfile, loc, &tent);
  226.     }
  227.     if  (tent.t_reflo > refpos)  {
  228.         tent.t_reflo = refpos;
  229.         putte(&mainfile, loc, &tent);
  230.     }
  231.     return    tent.t_lab;
  232. }
  233.  
  234. /*
  235.  *    Note references to data.
  236.  */
  237.  
  238. void    mkdref(tpos, size)
  239. long    tpos;
  240. unsigned  size;
  241. {
  242.     t_entry    tent;
  243.     d_entry    dent;
  244.     register  symbol  ds;
  245.     int    dchng = 0;
  246.     int    wsize;
  247.     long    dpos;
  248.     
  249.     gette(&mainfile, tpos, &tent);
  250.     if  (tent.t_relsymb != NULL)
  251.         return;
  252.         
  253.     dpos = gettw(&mainfile, tpos, R_LONG);
  254.     if  (dpos < mainfile.ef_dbase  ||  dpos > mainfile.ef_end)
  255.         return;
  256.     
  257.     switch  (size)  {
  258.     default:
  259.         wsize = D_BYTE;
  260.         break;
  261.     case  2:
  262.         wsize = D_WORD;
  263.         break;
  264.     case  4:
  265.         wsize = D_LONG;
  266.         break;
  267.     }
  268.     
  269.     getde(&mainfile, dpos, &dent);
  270.     if  ((ds = dent.d_lab) == NULL)  {
  271.         if  (dpos >= mainfile.ef_bbase)  {
  272.             ds = inventsymb("BS");
  273.             ds->s_type = S_BSS;
  274.         }
  275.         else  {
  276.             ds = inventsymb("DS");
  277.             ds->s_type = S_DATA;
  278.         }
  279.         ds->s_value = dpos;
  280.         dent.d_lab = ds;
  281.         dchng++;
  282.     }
  283.     else
  284.         ds->s_used++;
  285.  
  286.     if  (dent.d_type != D_BYTE)  {
  287.         if  (dent.d_type != wsize)  {
  288.             if  (dent.d_type == D_ADDR)  {
  289.                 if  (wsize != D_LONG)
  290.                     unimpl("Addr word usage");
  291.             }
  292.             else  if  (dent.d_type > wsize)  {
  293.                 dchng++;
  294.                 dent.d_type = wsize;
  295.                 dent.d_lng = size;
  296.             }
  297.         }
  298.     }
  299.     else  {
  300.         dent.d_type = wsize;
  301.         dent.d_lng = size;
  302.         dchng++;
  303.     }
  304.     if  (dchng)  {
  305.         putde(&mainfile, dpos, &dent);
  306.         for  (dchng = 1;  dchng < size; dchng++)
  307.             setde(&mainfile, dpos+dchng, D_CONT, 1);
  308.     }
  309.         
  310.     tent.t_relsymb = ds;
  311.     putte(&mainfile, tpos, &tent);
  312. }
  313.  
  314. /*
  315.  *    Add item to common or abs list.
  316.  */
  317.  
  318. #define    COMINC    10
  319.  
  320. void    addit(cp, symb)
  321. register  struct  commit  *cp;
  322. symbol    symb;
  323. {
  324.     if  (cp->c_int >= cp->c_max)  {
  325.         cp->c_max += COMINC;
  326.         if  (cp->c_symb == NULL)
  327.             cp->c_symb = (symbol *) malloc(COMINC*sizeof(symbol));
  328.         else
  329.             cp->c_symb = (symbol *)
  330.                     realloc(cp->c_symb,
  331.                         cp->c_max * sizeof(symbol));
  332.         if  (cp->c_symb == NULL)
  333.             nomem();
  334.     }
  335.     cp->c_symb[cp->c_int++] = symb;
  336. }
  337.